#include "flash.h"

/*==== Loader ====*/
#define ERASE_CMD           (1)
#define WRITE_CMD           (2)
#define READ_CMD            (3)
#define PROBE_CMD           (4)

#define RETURN_OK           (0)
#define RETURN_ERROR        (0x1 << 31)

typedef int (*tpfFLASH_DRV_Init)     (uint32_t *spi_base);
typedef int (*tpfFLASH_DRV_Erase)    (uint32_t *spi_base, uint32_t start_addr, uint32_t end_addr);
typedef int (*tpfFLASH_DRV_Write)     (uint32_t *spi_base, uint8_t* buffer, uint32_t offset, uint32_t count);
typedef int (*tpfFLASH_DRV_Read)   (uint32_t *spi_base, uint8_t* buffer, uint32_t offset, uint32_t count);

typedef struct
{
    tpfFLASH_DRV_Init       pfFLASH_DRV_Init;
    tpfFLASH_DRV_Erase      pfFLASH_DRV_Erase;
    tpfFLASH_DRV_Write      pfFLASH_DRV_Write;
    tpfFLASH_DRV_Read       pfFLASH_DRV_Read;
} tFlashDriverAPIInfo;

/* TODO S32K_FlashDrv: #02 本偏移量需与 .ld 链接文件中的 m_NVM_Driver 起始地址保持一致 */
#define FLASH_DRV_OFFSET    (0x8001f000u)
#define CAL_OFFSET(funcPtr) ((uint32_t)(funcPtr) - FLASH_DRV_OFFSET)

//-fPIC 生成的是位置无关的汇编代码，另外需要注意，要用—O0优化等级，防止被优化掉这个常量数组
NVM_DRIVER_SECTION static const volatile tFlashDriverAPIInfo gs_FlashDriverAPI  =
{
    (tpfFLASH_DRV_Init)     CAL_OFFSET(flash_init),
    (tpfFLASH_DRV_Erase)    CAL_OFFSET(flash_erase),
    (tpfFLASH_DRV_Write)    CAL_OFFSET(flash_write),
    (tpfFLASH_DRV_Read)     CAL_OFFSET(flash_read),
};

int loader_main(uint32_t cs, uint32_t *spi_base, uint32_t params1, uint32_t params2, uint32_t params3)
{
    int retval = 0;
    unsigned long params1_temp = params1;
    switch (cs)
    {
    case ERASE_CMD:
        retval = flash_erase(spi_base, params1, params2);
        break;
    case WRITE_CMD:
        retval = flash_write(spi_base, (uint8_t*)params1_temp, params2, params3);
        break;
    case READ_CMD:
        retval = flash_read(spi_base, (uint8_t*)params1_temp, params2, params3);
        break;
    case PROBE_CMD:
        retval = flash_init(spi_base);
        break;
    default:
        retval = RETURN_ERROR;
        break;
    }

    return retval;
}
